package cz.farin.mandelinka;


/**
 * Informace o polích těsně kolem brouka.
 */
public class Surroundings {
	
	private Square[] squares = new Square[10];
	
	
	public Surroundings() {
		for(int i = 0; i < squares.length; i++) {
			squares[i] = new Square();
		}
	}
	
	
	/**
	 * Vraci info o políčku v prislušném směru od brouka.   
	 */
	public Square get(Direction direction) {
		switch (direction) {
			case N: return get(0,-1);			
			case NE: return get(1,-1);
			case E: return get(1,0);
			case SE: return get(1,1);
			case S: return get(0,1);
			case SW: return get(-1,1);
			case W: return get(-1,0);
			case NW: return get(-1,-1);
		}
		throw new IllegalArgumentException();
	}
	
	/**
	 * Vraci info o políčku pod broukem   
	 */
	public Square getCenterSquare() {
		return get(0,0);
	}
	
	/**
	 * Vrací info o vlastním broukovi.   
	 */
	public BugInfo getMyBugInfo() {
		return getCenterSquare().getBugInfo();
	}
	
	/**
	 * Vrati pole relativne k otočení brouka, Direction.N znamena pred brokem
	 * Direction.S je za broukem atd.
	 * @param direction
	 */
	public Square getRelative(Direction direction) {		
		return get(relativeDirection(direction));
	}
	
	
	/**
	 * Vrací pole před broukem (závisí na otočení brouka)
	 * Zkratka pro getRelative(Direction.N)
	 * @return
	 */
	public Square getForward() {
		return getRelative(Direction.N);
	}
	
	/**
	 * Vrací pole za broukem (závisí na otočení brouka)
	 * Zkratka pro getRelative(Direction.S)
	 * @return
	 */
	public Square getBackward() {
		return getRelative(Direction.S);
	}
	
	/**
	 * Vrací pole vlevo od brouka (závisí na otočení brouka)
	 * Zkratka pro getRelative(Direction.W)
	 * @return
	 */
	public Square getLeft() {
		return getRelative(Direction.W);
	}
	
	/**
	 * Vrací pole vpravo od brouka (závisí na otočení brouka)
	 * Zkratka pro getRelative(Direction.E)
	 * @return
	 */
	public Square getRight() {
		return getRelative(Direction.E);
	}
	
	//private methods
		
	protected Direction relativeDirection(Direction direction) {
		Direction bugRotation = getMyBugInfo().getRotation();
		return Direction.values()[(bugRotation.ordinal() + direction.ordinal()) % 8];
	}
	
	private int cordsTpinternalIndex(int x, int y) {
		if (x == 0 && y == 0) return 0;
		return 1 + 3*(x+1) + (y+1); 
	}
	
	Square get(int x, int y) {
		if (x < -1 || x > 1 || y < -1 || y > 1) {
			throw new IllegalArgumentException("Coordinate value must be -1, 0 or 1"); 
		}		
		return squares[cordsTpinternalIndex(x, y)];
	}	
	
	void clearBugInfo() {
		for(Square sq: squares) {
			sq.setBugInfo(null);
		}
	}
	

}
